package com.sunyard.manage.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.sunyard.dal.bo.role.RolePopedomBO;
import com.sunyard.dal.bo.role.RolePopedomConfigBO;
import com.sunyard.dal.bo.role.RolePopedomQueryBO;
import com.sunyard.dal.dto.ButtonAddReqDTO;
import com.sunyard.dal.dto.PopedomAddReqDTO;
import com.sunyard.dal.entity.Operator;
import com.sunyard.dal.entity.Organization;
import com.sunyard.dal.entity.Popedom;
import com.sunyard.dal.entity.Role;
import com.sunyard.dal.entity.RoleCopy;
import com.sunyard.dal.entity.RolePopedom;
import com.sunyard.dal.mapper.OperatorMapper;
import com.sunyard.dal.mapper.OrganizationMapper;
import com.sunyard.dal.mapper.PopedomMapper;
import com.sunyard.dal.mapper.RoleCopyMapper;
import com.sunyard.dal.mapper.RoleMapper;
import com.sunyard.enums.PopedomTypeEnum;
import com.sunyard.manage.helper.PopedomHelper;
import com.sunyard.manage.service.OrganizationService;
import com.sunyard.manage.service.PopedomService;
import com.sunyard.redisUtil.RedisUtils;
import com.sunyard.utils.PrimaryKeyUtil;
import com.sunyard.utils.Response.BaseResult;
import com.sunyard.utils.Response.GetResult;
import com.sunyard.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

/**
 *  * @Description:权限管理 服务层接口实现类
 *  * @author:zhangbo
 *  * @date:2017年7月17日 上午9:48:18
 *  
 */
@Service
@Slf4j
public class PopedomServiceImpl implements PopedomService {

    @Autowired
    private PopedomMapper popedomMapper;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleCopyMapper roleCopyMapper;

    @Autowired
    private OperatorMapper operatorMapper;

    @Autowired
    OrganizationService organizationService;


    @Value("${admin.name}")
    private String adminName;

    @Value("${auditor.name}")
    private String auditor;

    @Value("${operator.role.id}")
    private String operatorRole;

    @Value("${auditor.role.id}")
    private String auditorRole;

    @Autowired
    private RedisUtils redisUtils;


    @Override
    public List<Popedom> findByUserId(String opId) {
        List<Popedom> list = popedomMapper.findByUserId(opId);
        return list;
    }

    /**
     * @Description: 获取机构权限树
     * @Author: jiy.fang
     * @Date: 2019/7/26 10:09
     */
    @Override
    public BaseResult<List<Popedom>> findPopedomTreeByOpId(HttpServletRequest request, String orgId, String orgPid) throws Exception {

        String orgId1 = TokenUtil.getOrgId(request.getHeader("token"));
        //判断能否进行权限分配
        //登录人所属机构
        Organization organization = organizationMapper.getOrganizationByOrgId(orgId);
        if (organization == null) {
            return GetResult.getResultFail("机构不存在，无法分配权限");
        }
        //判断是否为顶层机构
        if ("0".equals(orgPid)) {
            return GetResult.getResultFail("总行拥有所有功能权限，不支持重新分配");
        }
        //添加机构时需比对操作员机构,只能添加操作员所属机构的下属机构
        List<String> orgList = getListOrgIds(orgId1);
        if (!orgList.contains(orgId) && !orgId1.equals(orgId)) {
            return GetResult.getResultFail("权限配置失败，无配置权限");
        }
        List<Popedom> list = popedomMapper.getPopedomByOrgId(orgPid);
        List<Popedom> tree = PopedomHelper.getTree(list);
        return GetResult.getResult(tree);
    }

    /**
     * @Description: 角色权限分配
     * @Author: jiy.fang
     * @Date: 2019/7/27 9:16
     */
    @Override
    public BaseResult configRolePopedom(HttpServletRequest request, RolePopedomConfigBO configBO, RoleCopy roleCopy) throws Exception {
        //角色权限分配进入审核
        String opId = TokenUtil.getOpId(request.getHeader("token"));
        String orgId = TokenUtil.getOrgId(request.getHeader("token"));
        Organization organization = organizationMapper.getOrganizationByOrgId(orgId);
        //判断角色绑定的机构是否处于机构删除审核状态
        //被修改角色不在审核中
        int roleCopyExist = roleCopyMapper.countRoleCopyByRoleId(configBO.getRoleId());
        if (roleCopyExist > 0) {
            return GetResult.getResultFail("该角色存在审核记录，无法进行其他操作");
        }
        //限制不能修改自己角色权限
        Operator operator = operatorMapper.getOperatorByOpId(opId);
        String loginRole = operator.getRoleId();
        if (!loginRole.equals(operatorRole) && !loginRole.equals(auditorRole) && loginRole.equals(configBO.getRoleId())) {
            return GetResult.getResultFail("不能修改自己角色权限");
        }

        //前端传过来的权限
        List<String> popedoms = configBO.getPopedomList();

        //将重新分配的权限添加到角色权限临时表
        List<RolePopedom> rolePopedomList = new ArrayList<>();

        /**
         * 查询审核序号
         */
        Integer maxAuditSn = roleCopyMapper.maxAuditSn(configBO.getRoleId());
        /**
         * 当前审核序号
         */
        int nextAuditSn = maxAuditSn + 1;
        String auditId = PrimaryKeyUtil.getPrimaryKey();
        popedoms.forEach(popedomId -> {
            RolePopedom rolePopedom = new RolePopedom();
            rolePopedom.setRoleId(configBO.getRoleId());
            rolePopedom.setPopedomId(popedomId);
            rolePopedom.setAuditSn(nextAuditSn);
            rolePopedom.setAuditId(auditId);
            rolePopedomList.add(rolePopedom);
        });

        //如果是同步审核 修改角色权限直接通过
        if ("1".equals(organization.getAuditType())) {
            //删除机构权限表原有的权限 删除临时表权限数据
            popedomMapper.deleteRolePopedom(configBO.getRoleId());
            int i = popedomMapper.insertRolePopedom(rolePopedomList);
            //删除机构权限表原有的权限 删除临时表权限数据
            if (i > 0) {
                //详细日志添加
                return GetResult.getResultSuccess("角色权限修改成功！");
            }
            return GetResult.getResultErr("角色权限修改失败！");
        }

        int result = 0;
        if (!rolePopedomList.isEmpty()) {
            result = popedomMapper.insertRolePopedomTep(rolePopedomList);
            if (result == 0) {
                return GetResult.getResultFail("权限分配失败");
            }
        }
        return GetResult.getResultSuccess("权限分配成功，待审核");
    }

    /**
     * @Description: 获取角色可选权限树
     * @Author: jiy.fang
     * @Date: 2019/8/5 15:25
     */
    @Override
    public BaseResult findRolePopedomTreeByOpId(HttpServletRequest request, RolePopedomQueryBO queryBO) throws Exception {
        //只有超级管理员能配置权限
        Role role = roleMapper.getRoleByRoleId(queryBO.getRoleId());
        //查询角色所拥有的权限
        List<Popedom> popedomList = popedomMapper.getPopedomByOrgId(role.getRoleId());
        List<Popedom> tree = PopedomHelper.getTree(popedomList);
        return GetResult.getResult(tree);
    }

    /**
     * @Description: 查询待分配角色已经拥有的权限
     * @Author: jiy.fang
     * @Date: 2019/8/5 15:32
     */
    @Override
    public BaseResult findRoleOwnPopedomTreeByRoleId(String roleId) throws Exception {
        List<String> list = popedomMapper.findPopedomTreeByRoleId(roleId);
        return GetResult.getResult(list);
    }

    @Override
    public BaseResult findAllpopedom() {
        List<Popedom> popedomList = popedomMapper.getAllpopedom();
        List<Popedom> tree = PopedomHelper.getTree(popedomList);
        return GetResult.getResult(tree);
    }

    @Override
    public int findPopedomByUrl(String url) {
        return popedomMapper.findPopedomByUrl(url);
    }


    public List<String> getListPopedomIds(String popedomId) {
        List<String> lists = new ArrayList<>();
        recursiveGetPopedomIds(lists, popedomId);
        return lists;
    }

    //递归查询子菜单
    private void recursiveGetPopedomIds(List<String> lists, String popedomId) {
        List<String> popedomIdList = popedomMapper.getPopedomIdsList(popedomId);
        while (popedomIdList.isEmpty()) {
            return;
        }
        popedomIdList.forEach(childOrgId -> {
            lists.add(childOrgId);
            recursiveGetOrgId(lists, childOrgId);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult addPopedom(PopedomAddReqDTO addReqDTO) {
        log.info("权限添加请求入参：{}", JSON.toJSONString(addReqDTO));
        //判断菜单是否为一级菜单
        String firstPopedomPid = "0";
        if (firstPopedomPid.equals(addReqDTO.getPopedomPid())) {
            //添加一级菜单
            try {
                return insertFistPopedom(addReqDTO);
            } catch (Exception e) {
                return GetResult.getResultFail(e.getMessage());
            }
        } else {
            //如果按钮列表为空，则为添加菜单
            if (ObjectUtil.isEmpty(addReqDTO.getButtonList())) {
                validOtherPopedom(addReqDTO);
                validPopedomName(addReqDTO.getPopedomName());
                String insert = insertOtherPopedom(addReqDTO, PopedomTypeEnum.POPEDOM_LIST.getCode());
                if (StringUtils.isBlank(insert)) {
                    return GetResult.getResultFail("添加失败");
                }
            } else {
                String insert = null;
                //如果按钮列表不为空，则存在添加按钮，先判断添加按钮前是否需要添加上级菜单
                if (StringUtils.isNotBlank(addReqDTO.getPopedomName())) {
                    if (StringUtils.isBlank(addReqDTO.getPopedomLink())) {
                        return GetResult.getResultFail("菜单路由不能为空");
                    }
                    validPopedomName(addReqDTO.getPopedomName());
                    insert = insertOtherPopedom(addReqDTO, PopedomTypeEnum.POPEDOM_LIST.getCode());
                }
                //添加按钮
                List<ButtonAddReqDTO> buttonList = addReqDTO.getButtonList();
                for (ButtonAddReqDTO button : buttonList) {
                    validButton(button);
                    PopedomAddReqDTO popedom = new PopedomAddReqDTO();
                    if (StringUtils.isBlank(insert)) {
                        popedom.setPopedomPid(addReqDTO.getPopedomPid());
                    } else {
                        popedom.setPopedomPid(insert);
                    }
                    popedom.setPopedomName(button.getButtonName());
                    String insertButton = insertOtherPopedom(popedom, button.getButtonType());
                    if (StringUtils.isBlank(insertButton)) {
                        return GetResult.getResultFail("添加失败");
                    }
                }
            }
        }
        return GetResult.getResultSuccess("添加成功");
    }

    @Override
    public BaseResult addRolePopedom(HttpServletRequest request, RolePopedomConfigBO configBO) throws Exception {
        //前端传过来的权限
        List<String> popedoms = configBO.getPopedomList();
        //将重新分配的权限添加到角色权限临时表
        List<RolePopedom> rolePopedomList = new ArrayList<>();
        //查询审核序号
        int maxAuditSn = roleCopyMapper.maxAuditSn(configBO.getRoleId());
        //当前审核序号
        int nextAuditSn = maxAuditSn + 1;
        String auditId = PrimaryKeyUtil.getPrimaryKey();
        popedoms.forEach(popedomId -> {
            RolePopedom rolePopedom = new RolePopedom();
            rolePopedom.setRoleId(configBO.getRoleId());
            rolePopedom.setPopedomId(popedomId);
            rolePopedom.setAuditSn(nextAuditSn);
            rolePopedom.setAuditId(auditId);
            rolePopedomList.add(rolePopedom);
        });
        int result = 0;
        if (!rolePopedomList.isEmpty()) {
            result = popedomMapper.insertRolePopedomTep(rolePopedomList);
            if (result == 0) {
                return GetResult.getResultFail("权限分配失败");
            }
        }
        return null;
    }

    private String insertOtherPopedom(PopedomAddReqDTO addReqDTO, String popedomType) {
        Popedom popedomDO = new Popedom();
        popedomDO.setPopedomPid(addReqDTO.getPopedomPid());
        popedomDO.setPopedomName(addReqDTO.getPopedomName());
        popedomDO.setPopedomLink(addReqDTO.getPopedomLink());
        popedomDO.setPopedomType(popedomType);
        popedomDO.setPopedomOrigin("0");
        String popedomId = null;
        int maxPopedomId = popedomMapper.getMaxPopedomId(addReqDTO.getPopedomPid()) + 1;
        if (maxPopedomId == 1) {
            popedomId = addReqDTO.getPopedomPid() + "0" + maxPopedomId;
        } else {
            popedomId = String.valueOf(maxPopedomId).length() % 2 != 0 ? "0" + maxPopedomId : String.valueOf(maxPopedomId);
        }
        popedomDO.setPopedomId(popedomId);
        int insert = popedomMapper.insert(popedomDO);
        if (insert > 0) {
            String roleId = operatorMapper.getAdminRoleId();
            List<RolePopedomBO> rolePopedomList = new ArrayList<>();
            RolePopedomBO rolePopedom = new RolePopedomBO();
            rolePopedom.setPopedomId(popedomId);
            rolePopedom.setRoleId(roleId);
            rolePopedomList.add(rolePopedom);
            int count = popedomMapper.getByRoleIdAndPodedomId(roleId, popedomId);
            if (count <= 0) {
                int insert1 = popedomMapper.insertRolePopedomList(rolePopedomList);
                if (insert1 > 0) {
                    return popedomId;
                }
            }
        }
        return null;
    }

    /**
     * 添加一级菜单
     *
     * @param addReqDTO
     * @return WebBaseResult<Object>
     **/
    private BaseResult insertFistPopedom(PopedomAddReqDTO addReqDTO) {
        if (StringUtils.isBlank(addReqDTO.getPopedomName())) {
            return GetResult.getResultFail("菜单名称不能为空");
        }
        if (StringUtils.isBlank(addReqDTO.getPopedomLink())) {
            return GetResult.getResultFail("菜单路由不能为空");
        }
        if (StringUtils.isBlank(addReqDTO.getPopedomIconcls())) {
            return GetResult.getResultFail("菜单图标不能为空");
        }
        validPopedomName(addReqDTO.getPopedomName());
        Popedom popedomDO = new Popedom();
        popedomDO.setPopedomPid(addReqDTO.getPopedomPid());
        popedomDO.setPopedomName(addReqDTO.getPopedomName());
        popedomDO.setPopedomLink(addReqDTO.getPopedomLink());
        popedomDO.setPopedomType(PopedomTypeEnum.POPEDOM_LIST.getCode());
        popedomDO.setPopedomIconcls(addReqDTO.getPopedomIconcls());
        popedomDO.setPopedomOrigin("0");
        int sort = popedomMapper.getMaxSort();
//        popedomDO.setPopedomSort(sort + 10);
        int maxPopedomId = popedomMapper.getMaxPopedomId(addReqDTO.getPopedomPid()) + 1;
        String popedomId = String.valueOf(maxPopedomId).length() % 2 != 0 ? "0" + maxPopedomId : String.valueOf(maxPopedomId);
        popedomDO.setPopedomId(popedomId);
        int insert = popedomMapper.insert(popedomDO);
        if (insert > 0) {
            String roleId = operatorMapper.getAdminRoleId();
            List<RolePopedomBO> rolePopedomList = new ArrayList<>();
            RolePopedomBO rolePopedom = new RolePopedomBO();
            rolePopedom.setPopedomId(popedomId);
            rolePopedom.setRoleId(roleId);
            rolePopedomList.add(rolePopedom);
            int count = popedomMapper.getByRoleIdAndPodedomId(roleId, popedomId);
            if (count <= 0) {
                int insert1 = popedomMapper.insertRolePopedomList(rolePopedomList);
                if (insert1 > 0) {
                    return GetResult.getResultSuccess("添加成功");
                }
            }
        }
        return GetResult.getResultFail("添加失败");
    }

    /**
     * 其他菜单校验
     *
     * @param addReqDTO [addReqDTO]
     **/
    private void validOtherPopedom(PopedomAddReqDTO addReqDTO) {
        Popedom select = popedomMapper.selectByPopedomPid(addReqDTO.getPopedomPid());
        if (ObjectUtil.isNull(select)) {
            throw new IllegalArgumentException("未查询到对应的父级菜单");
        }
        if (StringUtils.isBlank(addReqDTO.getPopedomName())) {
            throw new IllegalArgumentException("菜单名称不能为空");
        }
        if (StringUtils.isBlank(addReqDTO.getPopedomLink())) {
            throw new IllegalArgumentException("菜单路由不能为空");
        }
    }

    private void validPopedomName(String popedomName) {
        Popedom select = popedomMapper.selectByPopedomName(popedomName);
        if (ObjectUtil.isNotNull(select)) {
            throw new IllegalArgumentException("菜单名称已存在");
        }
    }

    /**
     * 按钮校验
     *
     * @param button [button]
     **/
    public void validButton(ButtonAddReqDTO button) {
        if (StringUtils.isBlank(button.getButtonName())) {
            throw new IllegalArgumentException("按钮名称不能为空");
        }
        if (StringUtils.isBlank(button.getButtonType())) {
            throw new IllegalArgumentException("按钮类型不能为空");
        }
    }

    public List<String> getListOrgIds(String orgId) {
        String strkey = "orgid:" + orgId;
        List<String> lists = redisUtils.get(strkey, List.class);
        if (lists == null) {
            lists = organizationService.getOrgIdsByOrgId(orgId);
            redisUtils.set(strkey, lists);
        }
        return lists;
    }

    //递归查询子机构
    private void recursiveGetOrgId(List<String> lists, String orgId) {
        List<String> orgIdList = organizationMapper.getOrgIdsList(orgId);
        while (orgIdList.isEmpty()) {
            return;
        }
        orgIdList.forEach(childOrgId -> {
            lists.add(childOrgId);
            recursiveGetOrgId(lists, childOrgId);
        });
    }
}
